@@ -16,6 +16,14 @@ export interface Lerpable<T> {
1616
1717export type BindingOrValue < T > = Binding < T > | T ;
1818
19+ type Bindable < T = unknown > = Binding < T > | NonNullable < T > ;
20+
21+ type ComposeBindings < T extends Bindable [ ] > = {
22+ [ K in keyof T ] : T [ K ] extends Bindable < infer U > ? U : T [ K ] ;
23+ } ;
24+
25+ type BindingCombiner < T extends Bindable [ ] , U > = ( ...values : ComposeBindings < T > ) => U ;
26+
1927/**
2028 * Returns whether the given value is a binding.
2129 * @param value The value to check.
@@ -129,3 +137,20 @@ export function lerpBinding<T extends number | Lerpable<any>>(
129137 }
130138 } ) ;
131139}
140+
141+ /**
142+ * Composes multiple bindings or values together into a single binding.
143+ * Calls the combiner function with the values of the bindings when any
144+ * of the bindings change.
145+ * @param ...bindings A list of bindings or values.
146+ * @param combiner The function that maps the bindings to a new value.
147+ * @returns A binding that returns the result of the combiner.
148+ */
149+ export function composeBindings < T extends Bindable [ ] , U > ( ...bindings : [ ...T , BindingCombiner < T , U > ] ) : Binding < U > ;
150+
151+ export function composeBindings < T > ( ...values : [ ...Bindable [ ] , BindingCombiner < Bindable [ ] , T > ] ) : Binding < T > {
152+ const combiner = values . pop ( ) as BindingCombiner < Bindable [ ] , T > ;
153+ const bindings = values . map ( toBinding ) ;
154+
155+ return joinBindings ( bindings ) . map ( ( bindings ) => combiner ( ...bindings ) ) ;
156+ }
0 commit comments