Skip to content

Commit 50fe67b

Browse files
committed
feat: add composeBindings
1 parent 49eb065 commit 50fe67b

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

src/utils/binding.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ export interface Lerpable<T> {
1616

1717
export 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

Comments
 (0)