feat(vue): expand @robonen/vue composable collection

Composables, tests, category barrels, and README for @robonen/vue.
This commit is contained in:
2026-06-08 15:51:16 +07:00
parent 9a912f7a77
commit 59e995d0b5
369 changed files with 36554 additions and 188 deletions
@@ -0,0 +1,55 @@
import { isArray, sum } from '@robonen/stdlib';
import { computed, toValue } from 'vue';
import type { ComputedRef, MaybeRefOrGetter } from 'vue';
import type { MaybeComputedRefArgs } from '@/types';
/**
* @name useAverage
* @category Math
* @description Reactively compute the average (arithmetic mean) of the provided
* numbers. Accepts either a variadic list of numbers (each a ref, getter, or raw
* value) or a single reactive array whose items may themselves be refs/getters.
* Returns `NaN` when there are no values, mirroring `0 / 0`.
*
* @param {...MaybeRefOrGetter<number>} args The values to average, or a single reactive array of values
* @returns {ComputedRef<number>} A computed ref of the mean (`NaN` when empty)
*
* @example
* const a = ref(1);
* const b = ref(3);
* const avg = useAverage(a, b, 2); // 2
*
* @example
* const list = ref([1, 5, 3]);
* const avg = useAverage(list); // 3
*
* @example
* const list = ref([ref(2), () => 4, 6]);
* const avg = useAverage(list); // 4
*
* @since 0.0.15
*/
export function useAverage(array: MaybeRefOrGetter<Array<MaybeRefOrGetter<number>>>): ComputedRef<number>;
export function useAverage(...args: Array<MaybeRefOrGetter<number>>): ComputedRef<number>;
export function useAverage(...args: MaybeComputedRefArgs<number>): ComputedRef<number> {
return computed<number>(() => {
// Collect into a single flat numeric array so we can reuse stdlib `sum`
// and divide by the real count in one pass — no intermediate flatMap.
const values: number[] = [];
for (const arg of args) {
const value = toValue(arg);
if (isArray(value)) {
for (const inner of value)
values.push(toValue(inner));
}
else {
values.push(value);
}
}
// Empty -> NaN (0 / 0), matching the mathematical definition of a mean.
return sum(values) / values.length;
});
}