mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
docs: rewrite documentation (#25)
* docs: rewrite documentation * refactor: rename `Molecule` to `Selector` * refactor: replace all references to molecules * docs: rephrase intro * docs: remove italics * docs: fix typo * docs: update atom module names * docs: link example, add file names
This commit is contained in:
parent
833d5f8e86
commit
73ae0e6de4
17 changed files with 399 additions and 350 deletions
29
src/charm-sync/src/index.d.ts
vendored
29
src/charm-sync/src/index.d.ts
vendored
|
|
@ -1,4 +1,4 @@
|
|||
import { Atom, Molecule } from "@rbxts/charm";
|
||||
import { Atom, Selector } from "@rbxts/charm";
|
||||
|
||||
export = CharmSync;
|
||||
export as namespace CharmSync;
|
||||
|
|
@ -8,13 +8,18 @@ type Cleanup = () => void;
|
|||
declare namespace CharmSync {
|
||||
type AtomMap = Record<string, Atom<any>>;
|
||||
|
||||
type MoleculeMap = Record<string, Molecule<any>>;
|
||||
/**
|
||||
* @deprecated Use `SelectorMap` instead.
|
||||
*/
|
||||
type MoleculeMap = Record<string, Selector<any>>;
|
||||
|
||||
type SelectorMap = Record<string, Selector<any>>;
|
||||
|
||||
/**
|
||||
* Recursively infers the type of the state produced by a map of molecules.
|
||||
* Infers the type of the return values produced by a map of functions.
|
||||
*/
|
||||
type StateOfMap<T> = {
|
||||
[P in keyof T]: T[P] extends Molecule<infer State> ? State : never;
|
||||
[P in keyof T]: T[P] extends Selector<infer State> ? State : never;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -45,7 +50,7 @@ declare namespace CharmSync {
|
|||
* @param options The atoms to synchronize with the client.
|
||||
* @returns A `ServerSyncer` object.
|
||||
*/
|
||||
function server<Molecules extends MoleculeMap>(options: ServerOptions<Molecules>): ServerSyncer<Molecules>;
|
||||
function server<Selectors extends SelectorMap>(options: ServerOptions<Selectors>): ServerSyncer<Selectors>;
|
||||
|
||||
/**
|
||||
* Checks whether a value is `None`. If `true`, the value is scheduled to be
|
||||
|
|
@ -90,9 +95,9 @@ declare namespace CharmSync {
|
|||
* A payload that can be sent from the server to the client to synchronize
|
||||
* state between the two.
|
||||
*/
|
||||
type SyncPayload<Molecules extends MoleculeMap> =
|
||||
| { type: "init"; data: StateOfMap<Molecules> }
|
||||
| { type: "patch"; data: SyncPatch<StateOfMap<Molecules>> };
|
||||
type SyncPayload<Selectors extends SelectorMap> =
|
||||
| { type: "init"; data: StateOfMap<Selectors> }
|
||||
| { type: "patch"; data: SyncPatch<StateOfMap<Selectors>> };
|
||||
|
||||
interface ClientOptions<Atoms extends AtomMap> {
|
||||
/**
|
||||
|
|
@ -106,11 +111,11 @@ declare namespace CharmSync {
|
|||
ignoreUnhydrated?: boolean;
|
||||
}
|
||||
|
||||
interface ServerOptions<Molecules extends MoleculeMap> {
|
||||
interface ServerOptions<Selectors extends SelectorMap> {
|
||||
/**
|
||||
* The atoms to synchronize with the client.
|
||||
*/
|
||||
atoms: Molecules;
|
||||
atoms: Selectors;
|
||||
/**
|
||||
* The interval at which to send patches to the client, in seconds.
|
||||
* Defaults to `0` (patches are sent up to once per frame). Set to a
|
||||
|
|
@ -139,7 +144,7 @@ declare namespace CharmSync {
|
|||
sync(...payloads: SyncPayload<Atoms>[]): void;
|
||||
}
|
||||
|
||||
interface ServerSyncer<Molecules extends MoleculeMap> {
|
||||
interface ServerSyncer<Selectors extends SelectorMap> {
|
||||
/**
|
||||
* Sets up a subscription to each atom that schedules a patch to be sent to
|
||||
* the client whenever the state changes. When a change occurs, the `callback`
|
||||
|
|
@ -151,7 +156,7 @@ declare namespace CharmSync {
|
|||
* @param callback The function to call when the state changes.
|
||||
* @returns A cleanup function that unsubscribes all listeners.
|
||||
*/
|
||||
connect(callback: (player: Player, ...payloads: SyncPayload<Molecules>[]) => void): Cleanup;
|
||||
connect(callback: (player: Player, ...payloads: SyncPayload<Selectors>[]) => void): Cleanup;
|
||||
/**
|
||||
* Hydrates the client's state with the server's state. This should be
|
||||
* called when a player joins the game and requires the server's state.
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
local atom = require(script.Parent.atom)
|
||||
local store = require(script.Parent.store)
|
||||
local types = require(script.Parent.types)
|
||||
type Atom<T> = types.Atom<T>
|
||||
type AtomOptions<T> = types.AtomOptions<T>
|
||||
type Molecule<T> = types.Molecule<T>
|
||||
type Selector<T> = types.Selector<T>
|
||||
|
||||
--[=[
|
||||
Creates a read-only atom that derives its state from one or more atoms.
|
||||
Used to avoid unnecessary recomputations if multiple listeners depend on
|
||||
the same molecule.
|
||||
|
||||
@param molecule The function that produces the state.
|
||||
the same atoms.
|
||||
|
||||
@param callback The function that produces the state.
|
||||
@param options Optional configuration.
|
||||
@return A new read-only atom.
|
||||
]=]
|
||||
local function computed<T>(molecule: Molecule<T>, options: AtomOptions<T>?): Molecule<T>
|
||||
local dependencies, state = store.capture(molecule)
|
||||
local function computed<T>(callback: Selector<T>, options: AtomOptions<T>?): Selector<T>
|
||||
local dependencies, state = store.capture(callback)
|
||||
local computedAtom = atom(state, options)
|
||||
local computedRef = setmetatable({ current = computedAtom }, { __mode = "v" })
|
||||
|
||||
|
|
@ -24,7 +23,7 @@ local function computed<T>(molecule: Molecule<T>, options: AtomOptions<T>?): Mol
|
|||
|
||||
if computedAtom then
|
||||
store.disconnect(dependencies, listener)
|
||||
dependencies, state = store.capture(molecule)
|
||||
dependencies, state = store.capture(callback)
|
||||
store.connect(dependencies, listener, computedAtom)
|
||||
computedAtom(state)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type Cleanup = () -> ()
|
|||
@param callback The function to run.
|
||||
@return A function that unsubscribes the callback.
|
||||
]=]
|
||||
local function effect(callback: () -> (() -> ())?): () -> ()
|
||||
local function effect(callback: () -> Cleanup?): Cleanup
|
||||
local dependencies, cleanup = store.capture(callback)
|
||||
local disconnected = false
|
||||
|
||||
|
|
|
|||
65
src/charm/src/index.d.ts
vendored
65
src/charm/src/index.d.ts
vendored
|
|
@ -17,7 +17,7 @@ declare namespace Charm {
|
|||
* @param state The next state or a function that produces the next state.
|
||||
* @returns The current state, if no arguments are provided.
|
||||
*/
|
||||
interface Atom<State> extends Molecule<State> {
|
||||
interface Atom<State> extends Selector<State> {
|
||||
/**
|
||||
* @deprecated This property is not meant to be accessed directly.
|
||||
*/
|
||||
|
|
@ -26,21 +26,29 @@ declare namespace Charm {
|
|||
* @param state The next state or a function that produces the next state.
|
||||
* @returns The current state, if no arguments are provided.
|
||||
*/
|
||||
(state: State | ((prev: State) => State)): void;
|
||||
(state?: State | ((prev: State) => State)): State;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that depends on one or more atoms and produces a state. Can be
|
||||
* A function that depends on one or more atoms and produces a value. Can be
|
||||
* used to derive state from atoms.
|
||||
*
|
||||
* @returns The current state.
|
||||
*/
|
||||
type Molecule<State> = () => State;
|
||||
type Selector<State> = () => State;
|
||||
|
||||
/**
|
||||
* Infers the type of the state produced by the given molecule.
|
||||
* A function that depends on one or more atoms and produces a value. Can be
|
||||
* used to derive state from atoms.
|
||||
*
|
||||
* @returns The current state.
|
||||
*/
|
||||
type StateOf<T> = T extends Molecule<infer State> ? State : never;
|
||||
type Molecule<State> = Selector<State>;
|
||||
|
||||
/**
|
||||
* Infers the type of the state produced by the given function.
|
||||
*/
|
||||
type StateOf<T> = T extends Selector<infer State> ? State : never;
|
||||
|
||||
interface AtomOptions<State> {
|
||||
/**
|
||||
|
|
@ -66,24 +74,24 @@ declare namespace Charm {
|
|||
/**
|
||||
* Creates a read-only atom that derives its state from one or more atoms.
|
||||
* Used to avoid unnecessary recomputations if multiple listeners depend on
|
||||
* the same molecule.
|
||||
* the same atoms.
|
||||
*
|
||||
* @param molecule The function that produces the state.
|
||||
* @param callback The function that produces the state.
|
||||
* @param options Optional configuration.
|
||||
* @returns A new read-only atom.
|
||||
*/
|
||||
function computed<State>(molecule: Molecule<State>, options?: AtomOptions<State>): Molecule<State>;
|
||||
function computed<State>(callback: Selector<State>, options?: AtomOptions<State>): Selector<State>;
|
||||
|
||||
/**
|
||||
* Subscribes to changes in the given atom or molecule. The callback is
|
||||
* Subscribes to changes in the given atom or selector. The callback is
|
||||
* called with the current state and the previous state immediately after a
|
||||
* change occurs.
|
||||
*
|
||||
* @param molecule The atom or molecule to subscribe to.
|
||||
* @param callback The function to call when the state changes.
|
||||
* @param callback The atom or selector to subscribe to.
|
||||
* @param listener The function to call when the state changes.
|
||||
* @returns A function that unsubscribes the callback.
|
||||
*/
|
||||
function subscribe<State>(molecule: Molecule<State>, callback: (state: State, prev: State) => void): Cleanup;
|
||||
function subscribe<State>(callback: Selector<State>, listener: (state: State, prev: State) => void): Cleanup;
|
||||
|
||||
/**
|
||||
* Runs the given callback immediately and whenever any atom it depends on
|
||||
|
|
@ -98,11 +106,11 @@ declare namespace Charm {
|
|||
* Returns the result of the function without subscribing to changes. If a
|
||||
* non-function value is provided, it is returned as is.
|
||||
*
|
||||
* @param molecule The atom or molecule to get the state of.
|
||||
* @param args Arguments to pass to the molecule.
|
||||
* @param callback The atom or selector to get the state of.
|
||||
* @param args Arguments to pass to the function.
|
||||
* @returns The current state.
|
||||
*/
|
||||
function peek<State, Args extends unknown[]>(molecule: State | ((...args: Args) => State), ...args: Args): State;
|
||||
function peek<State, Args extends unknown[]>(callback: State | ((...args: Args) => State), ...args: Args): State;
|
||||
|
||||
/**
|
||||
* Returns whether the given value is an atom.
|
||||
|
|
@ -124,13 +132,14 @@ declare namespace Charm {
|
|||
* Captures all atoms that are read during the function call and returns them
|
||||
* along with the result of the function. Useful for tracking dependencies.
|
||||
*
|
||||
* @param molecule The function to run.
|
||||
* @param callback The function to run.
|
||||
* @returns A tuple containing the captured atoms and the result of the function.
|
||||
*/
|
||||
function capture<State>(molecule: Molecule<State>): LuaTuple<[dependencies: Set<Atom<unknown>>, state: State]>;
|
||||
function capture<State>(callback: Selector<State>): LuaTuple<[dependencies: Set<Atom<unknown>>, state: State]>;
|
||||
|
||||
/**
|
||||
* Notifies all subscribers of the given atom that the state has changed.
|
||||
* Mainly for running effects, since subscriptions check for equality.
|
||||
*
|
||||
* @param atom The atom to notify.
|
||||
*/
|
||||
|
|
@ -141,17 +150,17 @@ declare namespace Charm {
|
|||
* cleans up the instance when the item is removed. Returns a cleanup function
|
||||
* that unsubscribes all instances.
|
||||
*
|
||||
* @param molecule The atom or molecule to observe.
|
||||
* @param callback The atom or selector to observe.
|
||||
* @param factory The function that tracks the lifecycle of each item.
|
||||
* @returns A function that unsubscribes all instances.
|
||||
*/
|
||||
function observe<Item>(
|
||||
molecule: Molecule<readonly Item[]>,
|
||||
callback: Selector<readonly Item[]>,
|
||||
factory: (item: Item, index: number) => Cleanup | void,
|
||||
): Cleanup;
|
||||
|
||||
function observe<Key, Item>(
|
||||
molecule: Molecule<AnyMap<Key, Item>>,
|
||||
callback: Selector<AnyMap<Key, Item>>,
|
||||
factory: (item: Item, key: Key) => Cleanup | void,
|
||||
): Cleanup;
|
||||
|
||||
|
|
@ -161,22 +170,22 @@ declare namespace Charm {
|
|||
* When the atom changes, the `mapper` is called for each entry in the state
|
||||
* to compute the new state.
|
||||
*
|
||||
* @param molecule The atom or molecule to map.
|
||||
* @param callback The atom or selector to map.
|
||||
* @param mapper The function that maps each entry.
|
||||
* @returns A new atom with the mapped state.
|
||||
*/
|
||||
function mapped<V0, K1, V1>(
|
||||
molecule: Molecule<readonly V0[]>,
|
||||
callback: Selector<readonly V0[]>,
|
||||
mapper: (value: V0, index: number) => LuaTuple<[value: V1 | undefined, key: K1]>,
|
||||
): Molecule<ReadonlyMap<K1, V1>>;
|
||||
): Selector<ReadonlyMap<K1, V1>>;
|
||||
|
||||
function mapped<V0, V1>(
|
||||
molecule: Molecule<readonly V0[]>,
|
||||
callback: Selector<readonly V0[]>,
|
||||
mapper: (value: V0, index: number) => V1,
|
||||
): Molecule<readonly V1[]>;
|
||||
): Selector<readonly V1[]>;
|
||||
|
||||
function mapped<K0, V0, K1 = K0, V1 = V0>(
|
||||
molecule: Molecule<AnyMap<K0, V0>>,
|
||||
callback: Selector<AnyMap<K0, V0>>,
|
||||
mapper: (value: V0, key: K0) => LuaTuple<[value: V1 | undefined, key: K1]> | V1,
|
||||
): Molecule<ReadonlyMap<K1, V1>>;
|
||||
): Selector<ReadonlyMap<K1, V1>>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ local subscribe = require(script.subscribe)
|
|||
local types = require(script.types)
|
||||
|
||||
export type Atom<State> = types.Atom<State>
|
||||
export type Molecule<State> = types.Molecule<State>
|
||||
export type Selector<State> = types.Selector<State>
|
||||
export type Molecule<State> = types.Selector<State>
|
||||
export type SyncPayload = types.SyncPayload
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ local effect = require(script.Parent.effect)
|
|||
local store = require(script.Parent.store)
|
||||
local types = require(script.Parent.types)
|
||||
type Atom<T> = types.Atom<T>
|
||||
type Molecule<T> = types.Molecule<T>
|
||||
type Selector<T> = types.Selector<T>
|
||||
|
||||
type Map =
|
||||
(<K0, V0, K1, V1>(fn: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1)) -> Molecule<{ [K1]: V1 }>)
|
||||
& (<K0, V0, V1>(fn: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> V1?) -> Molecule<{ [K0]: V1 }>)
|
||||
& (<K0, V0, K1, V1>(fn: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1?)) -> Molecule<{ [K1]: V1 }>)
|
||||
(<K0, V0, K1, V1>(fn: Selector<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1)) -> Selector<{ [K1]: V1 }>)
|
||||
& (<K0, V0, V1>(fn: Selector<{ [K0]: V0 }>, mapper: (V0, K0) -> V1?) -> Selector<{ [K0]: V1 }>)
|
||||
& (<K0, V0, K1, V1>(fn: Selector<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1?)) -> Selector<{ [K1]: V1 }>)
|
||||
|
||||
--[=[
|
||||
Maps each entry in the atom's state to a new key-value pair. If the `mapper`
|
||||
|
|
@ -16,11 +16,11 @@ type Map =
|
|||
When the atom changes, the `mapper` is called for each entry in the state
|
||||
to compute the new state.
|
||||
|
||||
@param molecule The atom or molecule to map.
|
||||
@param callback The atom or selector to map.
|
||||
@param mapper The function that maps each entry.
|
||||
@return A new atom with the mapped state.
|
||||
]=]
|
||||
local function mapped<K0, V0, K1, V1>(molecule: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1?)): Molecule<{ [K1]: V1 }>
|
||||
local function mapped<K0, V0, K1, V1>(callback: Selector<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1?)): Selector<{ [K1]: V1 }>
|
||||
local mappedAtom = atom({})
|
||||
local mappedAtomRef = setmetatable({ current = mappedAtom }, { __mode = "v" })
|
||||
local prevMappedItems: { [K1]: V1 } = {}
|
||||
|
|
@ -31,7 +31,7 @@ local function mapped<K0, V0, K1, V1>(molecule: Molecule<{ [K0]: V0 }>, mapper:
|
|||
return unsubscribe()
|
||||
end
|
||||
|
||||
local items = molecule()
|
||||
local items = callback()
|
||||
local mappedItems = table.clone(store.peek(mappedAtomRef.current))
|
||||
local mappedKeys = {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
local effect = require(script.Parent.effect)
|
||||
local types = require(script.Parent.types)
|
||||
type Molecule<T> = types.Molecule<T>
|
||||
type Selector<T> = types.Selector<T>
|
||||
|
||||
local function noop() end
|
||||
|
||||
|
|
@ -9,15 +9,15 @@ local function noop() end
|
|||
cleans up the instance when the item is removed. Returns a cleanup function
|
||||
that unsubscribes all instances.
|
||||
|
||||
@param molecule The atom or molecule to observe.
|
||||
@param callback The atom or selector to observe.
|
||||
@param factory The function that tracks the lifecycle of each item.
|
||||
@return A function that unsubscribes all instances.
|
||||
]=]
|
||||
local function observe<K, V>(molecule: Molecule<{ [K]: V }>, factory: (value: V, key: K) -> (() -> ())?): () -> ()
|
||||
local function observe<K, V>(callback: Selector<{ [K]: V }>, factory: (value: V, key: K) -> (() -> ())?): () -> ()
|
||||
local connections: { [K]: () -> () } = {}
|
||||
|
||||
local unsubscribe = effect(function()
|
||||
local state = molecule()
|
||||
local state = callback()
|
||||
|
||||
for key, disconnect in next, connections do
|
||||
if state[key] == nil then
|
||||
|
|
|
|||
|
|
@ -100,8 +100,8 @@ end
|
|||
Returns the result of the function without subscribing to changes. If a
|
||||
non-function value is provided, it is returned as is.
|
||||
|
||||
@param molecule The atom or molecule to get the state of.
|
||||
@param args Arguments to pass to the molecule.
|
||||
@param callback The atom or selector to get the state of.
|
||||
@param args Arguments to pass to the function.
|
||||
@return The current state.
|
||||
]=]
|
||||
local function peek<T, U...>(callback: ((U...) -> T) | T, ...: U...): T
|
||||
|
|
@ -128,12 +128,12 @@ end
|
|||
Captures all atoms that are read during the function call and returns them
|
||||
along with the result of the function. Useful for tracking dependencies.
|
||||
|
||||
@param molecule The function to run.
|
||||
@param callback The function to run.
|
||||
@return A tuple containing the captured atoms and the result of the function.
|
||||
]=]
|
||||
local function capture<T>(molecule: () -> T): (Set<Atom<any>>, T)
|
||||
if listeners[molecule] then
|
||||
return { [molecule] = true }, peek(molecule)
|
||||
local function capture<T>(callback: () -> T): (Set<Atom<any>>, T)
|
||||
if listeners[callback] then
|
||||
return { [callback] = true }, peek(callback)
|
||||
end
|
||||
|
||||
local dependencies: Set<Atom<any>> = {}
|
||||
|
|
@ -141,7 +141,7 @@ local function capture<T>(molecule: () -> T): (Set<Atom<any>>, T)
|
|||
capturing.index += 1
|
||||
capturing.stack[capturing.index] = dependencies
|
||||
|
||||
local result = try(molecule, function()
|
||||
local result = try(callback, function()
|
||||
capturing.stack[capturing.index] = nil
|
||||
capturing.index -= 1
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
local store = require(script.Parent.store)
|
||||
local types = require(script.Parent.types)
|
||||
type Molecule<T> = types.Molecule<T>
|
||||
type Selector<T> = types.Selector<T>
|
||||
|
||||
--[=[
|
||||
Subscribes to changes in the given atom or molecule. The callback is
|
||||
Subscribes to changes in the given atom or selector. The callback is
|
||||
called with the current state and the previous state immediately after a
|
||||
change occurs.
|
||||
|
||||
@param molecule The atom or molecule to subscribe to.
|
||||
@param callback The function to call when the state changes.
|
||||
@param callback The atom or selector to subscribe to.
|
||||
@param listener The function to call when the state changes.
|
||||
@return A function that unsubscribes the callback.
|
||||
]=]
|
||||
local function subscribe<T>(molecule: Molecule<T>, callback: (state: T, prev: T) -> ()): () -> ()
|
||||
local dependencies, state = store.capture(molecule)
|
||||
local function subscribe<T>(callback: Selector<T>, listener: (state: T, prev: T) -> ()): () -> ()
|
||||
local dependencies, state = store.capture(callback)
|
||||
local disconnected = false
|
||||
|
||||
local function listener()
|
||||
local function handler()
|
||||
local prevState = state
|
||||
|
||||
store.disconnect(dependencies, listener)
|
||||
dependencies, state = store.capture(molecule)
|
||||
store.disconnect(dependencies, handler)
|
||||
dependencies, state = store.capture(callback)
|
||||
|
||||
if not disconnected then
|
||||
store.connect(dependencies, listener)
|
||||
store.connect(dependencies, handler)
|
||||
end
|
||||
|
||||
if state ~= prevState then
|
||||
callback(state, prevState)
|
||||
listener(state, prevState)
|
||||
end
|
||||
end
|
||||
|
||||
store.connect(dependencies, listener)
|
||||
store.connect(dependencies, handler)
|
||||
|
||||
return function()
|
||||
if not disconnected then
|
||||
disconnected = true
|
||||
store.disconnect(dependencies, listener)
|
||||
store.disconnect(dependencies, handler)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export type WeakMap<K, V> = typeof(setmetatable({} :: { [K]: V }, { __mode = "k"
|
|||
@param state The next state or a function that produces the next state.
|
||||
@return The current state, if no arguments are provided.
|
||||
]=]
|
||||
export type Atom<T> = (() -> T) & (state: T | (T) -> T) -> T
|
||||
export type Atom<T> = (state: (T | (T) -> T)?) -> T
|
||||
|
||||
--[=[
|
||||
A function that depends on one or more atoms and produces a state. Can be
|
||||
|
|
@ -18,7 +18,7 @@ export type Atom<T> = (() -> T) & (state: T | (T) -> T) -> T
|
|||
@template State The type of the state.
|
||||
@return The current state.
|
||||
]=]
|
||||
export type Molecule<T> = () -> T
|
||||
export type Selector<T> = () -> T
|
||||
|
||||
--[=[
|
||||
Optional configuration for creating an atom.
|
||||
|
|
|
|||
10
src/react/src/index.d.ts
vendored
10
src/react/src/index.d.ts
vendored
|
|
@ -1,15 +1,15 @@
|
|||
import { Molecule } from "@rbxts/charm";
|
||||
import { Selector } from "@rbxts/charm";
|
||||
|
||||
/**
|
||||
* A hook that subscribes to changes in the given atom or molecule. The
|
||||
* A hook that subscribes to changes in the given atom or selector. The
|
||||
* component is re-rendered whenever the state changes.
|
||||
*
|
||||
* If the `dependencies` array is provided, the subscription to the atom or
|
||||
* molecule is re-created whenever the dependencies change. Otherwise, the
|
||||
* selector is re-created whenever the dependencies change. Otherwise, the
|
||||
* subscription is created once when the component is mounted.
|
||||
*
|
||||
* @param molecule The atom or molecule to subscribe to.
|
||||
* @param callback The atom or selector to subscribe to.
|
||||
* @param dependencies An array of values that the subscription depends on.
|
||||
* @returns The current state.
|
||||
*/
|
||||
export function useAtom<State>(molecule: Molecule<State>, dependencies?: unknown[]): State;
|
||||
export function useAtom<State>(callback: Selector<State>, dependencies?: unknown[]): State;
|
||||
|
|
|
|||
|
|
@ -4,23 +4,23 @@ local React = if script.Parent:FindFirstChild("react")
|
|||
else require(script.Parent.React)
|
||||
|
||||
--[=[
|
||||
A hook that subscribes to changes in the given atom or molecule. The
|
||||
A hook that subscribes to changes in the given atom or selector. The
|
||||
component is re-rendered whenever the state changes.
|
||||
|
||||
If the `dependencies` array is provided, the subscription to the atom or
|
||||
molecule is re-created whenever the dependencies change. Otherwise, the
|
||||
selector is re-created whenever the dependencies change. Otherwise, the
|
||||
subscription is created once when the component is mounted.
|
||||
|
||||
@param molecule The atom or molecule to subscribe to.
|
||||
@param callback The atom or selector to subscribe to.
|
||||
@param dependencies An array of values that the subscription depends on.
|
||||
@return The current state.
|
||||
]=]
|
||||
local function useAtom<State>(molecule: Charm.Molecule<State>, dependencies: { any }?): State
|
||||
local state, setState = React.useState(molecule)
|
||||
local function useAtom<State>(callback: Charm.Selector<State>, dependencies: { any }?): State
|
||||
local state, setState = React.useState(callback)
|
||||
|
||||
React.useEffect(function()
|
||||
setState(molecule())
|
||||
return Charm.subscribe(molecule, setState)
|
||||
setState(callback())
|
||||
return Charm.subscribe(callback, setState)
|
||||
end, dependencies or {})
|
||||
|
||||
return state
|
||||
|
|
|
|||
6
src/vide/src/index.d.ts
vendored
6
src/vide/src/index.d.ts
vendored
|
|
@ -1,9 +1,9 @@
|
|||
import { Molecule } from "@rbxts/charm";
|
||||
import { Selector } from "@rbxts/charm";
|
||||
|
||||
/**
|
||||
* Subscribes to the state of an atom and returns a Vide source.
|
||||
*
|
||||
* @param molecule The atom or molecule to subscribe to.
|
||||
* @param callback The atom or selector to subscribe to.
|
||||
* @returns The reactive source.
|
||||
*/
|
||||
export function useAtom<T>(atom: Molecule<T>): () => T;
|
||||
export function useAtom<T>(callback: Selector<T>): () => T;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ local Vide = if script.Parent:FindFirstChild("vide")
|
|||
--[=[
|
||||
Subscribes to the state of an atom and returns a Vide source.
|
||||
|
||||
@param molecule The atom or molecule to subscribe to.
|
||||
@param callback The atom or selector to subscribe to.
|
||||
@return The reactive source.
|
||||
]=]
|
||||
local function useAtom<State>(molecule: () -> State): State
|
||||
local state = Vide.source(molecule())
|
||||
local unsubscribe = Charm.subscribe(molecule, function(value)
|
||||
local function useAtom<State>(callback: () -> State): State
|
||||
local state = Vide.source(callback())
|
||||
local unsubscribe = Charm.subscribe(callback, function(value)
|
||||
task.spawn(state, value)
|
||||
end)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue