context-state: combineStates

This commit is contained in:
Josep M Sobrepere 2022-10-05 23:23:05 +02:00
parent 8e62ef7aaf
commit 08e3ddc83d
No known key found for this signature in database
GPG Key ID: 9A207FDA2481C91A

View 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>
}