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} args The values to average, or a single reactive array of values * @returns {ComputedRef} 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.14 */ export function useAverage(array: MaybeRefOrGetter>>): ComputedRef; export function useAverage(...args: Array>): ComputedRef; export function useAverage(...args: MaybeComputedRefArgs): ComputedRef { return computed(() => { // 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; }); }