87 lines
1.9 KiB
TypeScript
87 lines
1.9 KiB
TypeScript
|
|
import { type ClassValue, clsx } from 'clsx';
|
||
|
|
import { twMerge } from 'tailwind-merge';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Merge Tailwind CSS classes
|
||
|
|
*/
|
||
|
|
export function cn(...inputs: ClassValue[]) {
|
||
|
|
return twMerge(clsx(inputs));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Clamp a value between min and max
|
||
|
|
*/
|
||
|
|
export function clamp(value: number, min: number, max: number): number {
|
||
|
|
return Math.min(Math.max(value, min), max);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Linear interpolation
|
||
|
|
*/
|
||
|
|
export function lerp(a: number, b: number, t: number): number {
|
||
|
|
return a + (b - a) * t;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Calculate distance between two points
|
||
|
|
*/
|
||
|
|
export function distance(x1: number, y1: number, x2: number, y2: number): number {
|
||
|
|
const dx = x2 - x1;
|
||
|
|
const dy = y2 - y1;
|
||
|
|
return Math.sqrt(dx * dx + dy * dy);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Snap value to grid
|
||
|
|
*/
|
||
|
|
export function snapToGrid(value: number, gridSize: number): number {
|
||
|
|
return Math.round(value / gridSize) * gridSize;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Format bytes to human readable string
|
||
|
|
*/
|
||
|
|
export function formatBytes(bytes: number, decimals = 2): string {
|
||
|
|
if (bytes === 0) return '0 Bytes';
|
||
|
|
|
||
|
|
const k = 1024;
|
||
|
|
const dm = decimals < 0 ? 0 : decimals;
|
||
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
|
|
|
||
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Debounce function
|
||
|
|
*/
|
||
|
|
export function debounce<T extends (...args: any[]) => any>(
|
||
|
|
func: T,
|
||
|
|
wait: number
|
||
|
|
): (...args: Parameters<T>) => void {
|
||
|
|
let timeout: NodeJS.Timeout | null = null;
|
||
|
|
|
||
|
|
return (...args: Parameters<T>) => {
|
||
|
|
if (timeout) clearTimeout(timeout);
|
||
|
|
timeout = setTimeout(() => func(...args), wait);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Throttle function
|
||
|
|
*/
|
||
|
|
export function throttle<T extends (...args: any[]) => any>(
|
||
|
|
func: T,
|
||
|
|
limit: number
|
||
|
|
): (...args: Parameters<T>) => void {
|
||
|
|
let inThrottle: boolean;
|
||
|
|
|
||
|
|
return (...args: Parameters<T>) => {
|
||
|
|
if (!inThrottle) {
|
||
|
|
func(...args);
|
||
|
|
inThrottle = true;
|
||
|
|
setTimeout(() => (inThrottle = false), limit);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|