chore: update eslint, housekeeping

This commit is contained in:
littensy 2025-09-25 15:17:08 -07:00
parent cb52ece4d3
commit 4a07297a13
14 changed files with 554 additions and 619 deletions

View file

@ -26,34 +26,34 @@ export function effect(callback: () => Cleanup | void): Cleanup;
export function effectScope(callback: () => Cleanup | void, detached?: boolean): Cleanup;
export function listen<T>(
callback: () => T,
getter: () => T,
listener: (value: T, previousValue: T | undefined, dispose: Cleanup) => void,
): Cleanup;
export function subscribe<T>(callback: () => T, listener: (value: T, previousValue: T) => void): Cleanup;
export function subscribe<T>(getter: () => T, listener: (value: T, previousValue: T) => void): Cleanup;
export function mapped<VI, KI, VO, KO = KI>(
callback: () => Map<KI, VI> | ReadonlyMap<KI, VI>,
getter: () => Map<KI, VI> | ReadonlyMap<KI, VI>,
mapper: (value: VI, key: KI) => LuaTuple<[VO, KO]> | VO,
): () => ReadonlyMap<KO, VO>;
// Overload for arrays
export function mapped<VI, VO, K extends Key = number>(
callback: () => readonly VI[],
getter: () => readonly VI[],
mapper: (value: VI, key: number) => LuaTuple<[VO, K]> | VO,
): () => K extends number ? readonly VO[] : { readonly [P in K]: VO };
// Overload for objects
export function mapped<VI, KI extends Key, VO, KO extends Key = KI>(
callback: () => { readonly [K in KI]: VI },
getter: () => { readonly [K in KI]: VI },
mapper: (value: VI, key: KI) => LuaTuple<[VO, KO]> | VO,
): () => { readonly [K in KO]: VO };
export function observe<V, K = number>(
callback: () => Map<K, V> | ReadonlyMap<K, V> | readonly V[],
getter: () => Map<K, V> | ReadonlyMap<K, V> | readonly V[],
observer: (value: V, key: K) => Cleanup | void,
): Cleanup;
// Overload for objects
export function observe<V, K extends Key>(
callback: () => { readonly [K in Key]: V },
getter: () => { readonly [K in Key]: V },
observer: (value: V, key: K) => Cleanup | void,
): Cleanup;

View file

@ -4,9 +4,9 @@ local untracked = require("./untracked")
local computed = core.computed
local effect = core.effect
local function listen<T>(selector: () -> T, listener: (state: T, previous: T?, dispose: () -> ()) -> ()): () -> ()
local function listen<T>(getter: () -> T, listener: (state: T, previous: T?, dispose: () -> ()) -> ()): () -> ()
local tracked = computed(function()
return selector()
return getter()
end)
local current: T

View file

@ -4,10 +4,10 @@ local computed = core.computed
local setCurrentSub = core.setCurrentSub
type Mapped =
& (<KI, VI, KO, VO>(selector: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)) -> () -> { [KO]: VO })
& (<K, VI, VO>(selector: () -> { [K]: VI }, mapper: (item: VI, key: K) -> VO) -> () -> { [K]: VO })
& (<KI, VI, KO, VO>(getter: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)) -> () -> { [KO]: VO })
& (<K, VI, VO>(getter: () -> { [K]: VI }, mapper: (item: VI, key: K) -> VO) -> () -> { [K]: VO })
local function mapped<KI, VI, KO, VO>(selector: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)): () -> { [KO]: VO }
local function mapped<KI, VI, KO, VO>(getter: () -> { [KI]: VI }, mapper: (item: VI, key: KI) -> (VO, KO)): () -> { [KO]: VO }
local currentData: { [KI]: VI } = {}
local keyCache: { [KI]: KO } = {}
@ -26,7 +26,7 @@ local function mapped<KI, VI, KO, VO>(selector: () -> { [KI]: VI }, mapper: (ite
return computed(function(previousOutput)
local currentOutput: { [KO]: VO } = previousOutput or {}
local previousData = currentData
currentData = selector()
currentData = getter()
for key in previousData do
if currentData[key] ~= nil then

View file

@ -6,7 +6,7 @@ local onCleanup = core.onCleanup
local startBatch = core.startBatch
local endBatch = core.endBatch
local function observe<K, V>(selector: () -> { [K]: V }, observer: (item: V, key: K) -> ...(() -> ())?): () -> ()
local function observe<K, V>(getter: () -> { [K]: V }, observer: (item: V, key: K) -> ...(() -> ())?): () -> ()
local scopes: { [K]: () -> () } = {}
local currentItems: { [K]: V } = {}
@ -37,7 +37,7 @@ local function observe<K, V>(selector: () -> { [K]: V }, observer: (item: V, key
local disposeEffect = effect(function()
local previousItems = currentItems
currentItems = selector()
currentItems = getter()
if currentItems ~= previousItems then
startBatch()
updateScopes(currentItems, previousItems)

View file

@ -4,9 +4,9 @@ local untracked = require("./untracked")
local computed = core.computed
local effect = core.effect
local function subscribe<T>(selector: () -> T, listener: (state: T, lastState: T) -> ()): () -> ()
local function subscribe<T>(getter: () -> T, listener: (state: T, lastState: T) -> ()): () -> ()
local tracked = computed(function()
return selector()
return getter()
end)
local current: T

View file

@ -37,6 +37,7 @@ test("tracks dependencies", function()
assert(hook.result == 0, "should return 0")
state(1)
assert(hook.result == 1, "should return 1")
state = atom(0)
hook.rerender()
assert(hook.result == 0, "should return 0")

View file

@ -37,6 +37,7 @@ test("tracks dependencies", function()
assert(hook.result:getValue() == 0, "should return 0")
state(1)
assert(hook.result:getValue() == 1, "should return 1")
state = atom(0)
hook.rerender()
assert(hook.result:getValue() == 0, "should return 0")

View file

@ -1,28 +1,23 @@
local Charm = require("./Charm")
local React = require("./React")
local effect = Charm.effect
local useBinding = React.useBinding
local useEffect = React.useEffect
local useState = React.useState
local useMemo = React.useMemo
--- A hook that subscribes to changes in the given atom or selector. The
--- component is re-rendered with the new state after an update.
---
--- If the `dependencies` array is provided, a new effect is created for the
--- current `callback` when the dependencies change. Otherwise, the effect is
--- current `getter` when the dependencies change. Otherwise, the effect is
--- created only once, when the component is mounted.
---
--- @param callback The atom or selector to watch.
--- @param dependencies An array of values used to memoize the callback.
--- @param getter The atom or selector to watch.
--- @param dependencies An array of values used to memoize the getter.
--- @return The current state.
local function useAtom<T>(callback: () -> T, dependencies: { any }?): T
local state, setState = useState(callback)
local function useAtom<T>(getter: () -> T, dependencies: { any }?): T
local state, setState = React.useState(getter)
useEffect(function()
return effect(function()
setState(callback())
React.useLayoutEffect(function()
setState(getter())
return Charm.effect(function()
setState(getter())
end)
end, dependencies or {})
@ -33,19 +28,20 @@ end
--- a binding that updates when the state changes.
---
--- If the `dependencies` array is provided, a new effect is created for the
--- current `callback` when the dependencies change. Otherwise, the effect is
--- current `getter` when the dependencies change. Otherwise, the effect is
--- created only once, when the component is mounted.
---
--- @param callback The atom or selector to watch.
--- @param dependencies An array of values used to memoize the callback.
--- @param getter The atom or selector to watch.
--- @param dependencies An array of values used to memoize the getter.
--- @return A binding that stores the current state.
local function useAtomBinding<T>(callback: () -> T, dependencies: { any }?)
local initialState = useMemo(callback, {})
local binding, setBinding = useBinding(initialState)
local function useAtomBinding<T>(getter: () -> T, dependencies: { any }?)
local initialState = React.useMemo(getter, {})
local binding, setBinding = React.useBinding(initialState)
useEffect(function()
return effect(function()
setBinding(callback())
React.useEffect(function()
setBinding(getter())
return Charm.effect(function()
setBinding(getter())
end)
end, dependencies or {})

View file

@ -5,14 +5,14 @@ local subscribe = Charm.subscribe
local source = Vide.source
local cleanup = Vide.cleanup
--- Subscribes to the state of an atom or selector. Returns a source that
--- updates when the state changes.
--- Returns a reactive source that updates when the given getter function's
--- value changes.
---
--- @param callback The atom or selector to subscribe to.
--- @param getter The atom or selector to subscribe to.
--- @return The reactive source.
local function useAtom<State>(callback: () -> State): () -> State
local state = source(callback())
cleanup(subscribe(callback, state))
local function useAtom<State>(getter: () -> State): () -> State
local state = source(getter())
cleanup(subscribe(getter, state))
return state
end