import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; /** * Utility function to merge Tailwind CSS classes with clsx support * Handles class merging, conflict resolution, and conditional classes */ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } /** * Utility function to check if a value is not null or undefined */ export function isNonNullable(value: T | null | undefined): value is T { return value != null; } /** * Utility function to format currency */ export function formatCurrency(amount: number, currency: string = 'EUR', locale: string = 'de-DE'): string { return new Intl.NumberFormat(locale, { style: 'currency', currency: currency, minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(amount); } /** * Utility function to format date */ export function formatDate(date: Date | string, locale: string = 'de-DE'): string { const d = typeof date === 'string' ? new Date(date) : date; return new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long', day: 'numeric', }).format(d); } /** * Utility function to generate slug from text */ export function generateSlug(text: string): string { return text .toLowerCase() .replace(/[^\w\s-]/g, '') .replace(/\s+/g, '-') .replace(/-+/g, '-') .trim(); } /** * Utility function to debounce function calls */ export function debounce any>( func: T, wait: number ): (...args: Parameters) => void { let timeout: NodeJS.Timeout; return (...args: Parameters) => { clearTimeout(timeout); timeout = setTimeout(() => func(...args), wait); }; } /** * Utility function to get initials from a name */ export function getInitials(name: string): string { return name .split(' ') .map(part => part[0]) .join('') .toUpperCase() .slice(0, 2); } /** * Utility function to truncate text */ export function truncate(text: string, maxLength: number, suffix = '...'): string { if (text.length <= maxLength) return text; return text.slice(0, maxLength - suffix.length) + suffix; }