76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
// ── Utility Functions ────────────────────────────────────────────────
|
|
// Auto-generated by self-healing setup. Edit .setup-templates/templates/utils.ts to customize.
|
|
|
|
import { clsx, type ClassValue } from "clsx";
|
|
import { twMerge } from "tailwind-merge";
|
|
|
|
export function cn(...inputs: ClassValue[]) {
|
|
return twMerge(clsx(inputs));
|
|
}
|
|
|
|
export function formatDate(date: Date | string, options?: Intl.DateTimeFormatOptions): string {
|
|
const d = typeof date === "string" ? new Date(date) : date;
|
|
return d.toLocaleDateString("en-US", {
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
...options,
|
|
});
|
|
}
|
|
|
|
export function formatTime(date: Date | string): string {
|
|
const d = typeof date === "string" ? new Date(date) : date;
|
|
return d.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", hour12: true });
|
|
}
|
|
|
|
export function formatCurrency(amount: number, currency = "USD"): string {
|
|
return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
|
|
}
|
|
|
|
export function truncate(str: string, length: number): string {
|
|
if (str.length <= length) return str;
|
|
return str.slice(0, length - 3) + "...";
|
|
}
|
|
|
|
export function generateId(): string {
|
|
return crypto.randomUUID();
|
|
}
|
|
|
|
export function debounce<T extends (...args: unknown[]) => unknown>(
|
|
fn: T,
|
|
delay: number
|
|
): (...args: Parameters<T>) => void {
|
|
let timeoutId: ReturnType<typeof setTimeout>;
|
|
return (...args: Parameters<T>) => {
|
|
clearTimeout(timeoutId);
|
|
timeoutId = setTimeout(() => fn(...args), delay);
|
|
};
|
|
}
|
|
|
|
export function throttle<T extends (...args: unknown[]) => unknown>(
|
|
fn: T,
|
|
limit: number
|
|
): (...args: Parameters<T>) => void {
|
|
let inThrottle = false;
|
|
return (...args: Parameters<T>) => {
|
|
if (!inThrottle) {
|
|
fn(...args);
|
|
inThrottle = true;
|
|
setTimeout(() => (inThrottle = false), limit);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function classNames(...classes: (string | boolean | undefined | null)[]): string {
|
|
return classes.filter(Boolean).join(" ");
|
|
}
|
|
|
|
export function sleep(ms: number): Promise<void> {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
export function retry<T>(fn: () => Promise<T>, retries = 3, delay = 1000): Promise<T> {
|
|
return fn().catch((err) =>
|
|
retries > 0 ? sleep(delay).then(() => retry(fn, retries - 1, delay * 2)) : Promise.reject(err)
|
|
);
|
|
} |