mirror of
https://github.com/re-rxjs/react-rxjs.git
synced 2025-12-08 18:01:51 +00:00
context-state: combineStates
This commit is contained in:
parent
8e62ef7aaf
commit
08e3ddc83d
47
packages/context-state/src/combineStates.ts
Normal file
47
packages/context-state/src/combineStates.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { of } from "rxjs"
|
||||
import {
|
||||
mapRecord,
|
||||
detachedNode,
|
||||
EMPTY_VALUE,
|
||||
recordEntries,
|
||||
children,
|
||||
} from "./internal"
|
||||
import { StateNode, StringRecord } from "./types"
|
||||
|
||||
type StringRecordNodeToNodeStringRecord<
|
||||
States extends StringRecord<StateNode<any>>,
|
||||
> = StateNode<{
|
||||
[K in keyof States]: States[K] extends StateNode<infer V> ? V : never
|
||||
}>
|
||||
|
||||
export const combineStates = <States extends StringRecord<StateNode<any>>>(
|
||||
states: States,
|
||||
): StringRecordNodeToNodeStringRecord<States> => {
|
||||
let inactiveStates = Object.keys(states).length
|
||||
let emptyStates = 0
|
||||
const activeStates = mapRecord(states, () => false)
|
||||
const latestStates = mapRecord(states, () => null)
|
||||
|
||||
const [result, run] = detachedNode(() => of({ ...latestStates }))
|
||||
|
||||
let latestValue: boolean | EMPTY_VALUE = false
|
||||
recordEntries(states).forEach(([key, node]) => {
|
||||
children.get(node)!.add((isActive, value) => {
|
||||
if (isActive !== activeStates[key]) {
|
||||
inactiveStates += isActive ? -1 : +1
|
||||
activeStates[key] = isActive
|
||||
}
|
||||
|
||||
if (value !== latestStates[key]) {
|
||||
emptyStates +=
|
||||
latestStates[key] === EMPTY_VALUE ? -1 : value === EMPTY_VALUE ? 1 : 0
|
||||
latestStates[key] = value
|
||||
}
|
||||
|
||||
latestValue = emptyStates === 0 ? !latestValue : EMPTY_VALUE
|
||||
run(inactiveStates === 0, latestValue)
|
||||
})
|
||||
})
|
||||
|
||||
return result as StringRecordNodeToNodeStringRecord<States>
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user