Files
stream.ui/src/lib/utils.ts

97 lines
2.5 KiB
TypeScript

import type { ClassValue } from "clsx";
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function debounce<Func extends (...args: any[]) => any>(func: Func, wait: number): Func {
let timeout: ReturnType<typeof setTimeout> | null;
return function (this: any, ...args: any[]) {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, wait);
} as Func;
}
type AspectInfo = {
width: number;
height: number;
ratio: string; // ví dụ: "16:9"
float: number; // ví dụ: 1.777...
};
function gcd(a: number, b: number): number {
return b === 0 ? a : gcd(b, a % b);
}
export function getImageAspectRatio(url: string): Promise<AspectInfo> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
const w = img.naturalWidth;
const h = img.naturalHeight;
const g = gcd(w, h);
resolve({
width: w,
height: h,
ratio: `${w / g}:${h / g}`,
float: w / h
});
};
img.onerror = () => reject(new Error("Cannot load image"));
img.src = url;
});
}
export const formatBytes = (bytes?: number) => {
if (!bytes) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
export const formatDuration = (seconds?: number) => {
if (!seconds) return '0:00';
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
if (h > 0) {
return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
}
return `${m}:${s.toString().padStart(2, '0')}`;
};
export const formatDate = (dateString?: string) => {
if (!dateString) return '';
return new Date(dateString).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
export const getStatusSeverity = (status: string = "") => {
switch (status) {
case 'success':
case 'ready':
return 'success';
case 'failed':
return 'danger';
case 'pending':
return 'warn';
default:
return 'info';
}
};