import { computed, type MaybeRefOrGetter, toValue, type Ref } from 'vue' /** * Limite le nombre de messages à `max` éléments. * Retourne le tableau inchangé si `max` est undefined ou <= 0. */ export function limitMessages(messages: string[], max?: number): string[] { return max && max > 0 ? messages.slice(0, max) : messages } /** * Déduplique et filtre les messages vides, puis limite le nombre. */ export function normalizeMessages(messages: string[], max?: number): string[] { return limitMessages( [...new Set(messages.filter(Boolean))], max, ) } /** * Fusionne des messages externes et internes en filtrant les messages vides, * en dédupliquant puis en limitant. */ export function mergeMessages( externalMessages: string[] | null | undefined, internalMessages: string[], max?: number, ): string[] { return limitMessages( [...new Set([ ...(externalMessages ?? []), ...internalMessages, ].filter(Boolean))], max, ) } /** * Options pour `useDisplayMessages`. */ export interface UseDisplayMessagesOptions { errors: Ref warnings: Ref successes: Ref externalErrors?: MaybeRefOrGetter externalWarnings?: MaybeRefOrGetter externalSuccesses?: MaybeRefOrGetter maxErrors?: MaybeRefOrGetter hasErrorProp?: MaybeRefOrGetter hasWarningProp?: MaybeRefOrGetter hasSuccessProp?: MaybeRefOrGetter internalHasSuccess?: Ref disableErrorHandling?: MaybeRefOrGetter } /** * Composable qui calcule les messages d'affichage et les flags de priorité * (erreur > avertissement > succès) à partir d'états internes et externes. */ export function useDisplayMessages(options: UseDisplayMessagesOptions) { const displayErrors = computed(() => { const max = toValue(options.maxErrors) const internal = toValue(options.disableErrorHandling) !== true ? options.errors.value : [] return mergeMessages( toValue(options.externalErrors) ?? null, internal, max, ) }) const displayWarnings = computed(() => { const max = toValue(options.maxErrors) const internal = toValue(options.disableErrorHandling) !== true ? options.warnings.value : [] return mergeMessages( toValue(options.externalWarnings) ?? null, internal, max, ) }) const displaySuccesses = computed(() => { const max = toValue(options.maxErrors) const internal = toValue(options.disableErrorHandling) !== true ? options.successes.value : [] return mergeMessages( toValue(options.externalSuccesses) ?? null, internal, max, ) }) const displayHasError = computed(() => displayErrors.value.length > 0 || Boolean(toValue(options.hasErrorProp)), ) const displayHasWarning = computed(() => displayWarnings.value.length > 0 || Boolean(toValue(options.hasWarningProp)), ) const displayHasSuccess = computed(() => ( ( (options.internalHasSuccess?.value ?? false) || (toValue(options.externalSuccesses)?.length ?? 0) > 0 ) && !displayHasError.value && !displayHasWarning.value ) || Boolean(toValue(options.hasSuccessProp))) return { displayErrors, displayWarnings, displaySuccesses, displayHasError, displayHasWarning, displayHasSuccess, } }