detect-tab
Version:
A comprehensive tab detection and management library for web applications
122 lines (107 loc) • 2.99 kB
text/typescript
/**
* Utility functions for tab detection
*/
/**
* Check if the Page Visibility API is supported
*/
export function isVisibilityAPISupported(): boolean {
return typeof document !== 'undefined' && 'visibilityState' in document;
}
/**
* Check if the browser is supported
*/
export function isBrowserSupported(): boolean {
return typeof window !== 'undefined' && typeof document !== 'undefined';
}
/**
* Get the browser-specific visibility property names
*/
export function getVisibilityProperties(): {
hidden: string;
visibilityChange: string;
} {
if (!isBrowserSupported()) {
return { hidden: 'hidden', visibilityChange: 'visibilitychange' };
}
let hidden: string;
let visibilityChange: string;
if (typeof document.hidden !== 'undefined') {
hidden = 'hidden';
visibilityChange = 'visibilitychange';
} else if (typeof (document as any).msHidden !== 'undefined') {
hidden = 'msHidden';
visibilityChange = 'msvisibilitychange';
} else if (typeof (document as any).webkitHidden !== 'undefined') {
hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange';
} else {
hidden = 'hidden';
visibilityChange = 'visibilitychange';
}
return { hidden, visibilityChange };
}
/**
* Debounce function to limit rapid event firing
*/
export function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: ReturnType<typeof setTimeout> | null = null;
return (...args: Parameters<T>): void => {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
func(...args);
}, wait);
};
}
/**
* Get current timestamp
*/
export function now(): number {
return Date.now();
}
/**
* Format time duration in human-readable format
*/
export function formatDuration(milliseconds: number): string {
const seconds = Math.floor(milliseconds / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) {
return `${days}d ${hours % 24}h ${minutes % 60}m ${seconds % 60}s`;
} else if (hours > 0) {
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
} else if (minutes > 0) {
return `${minutes}m ${seconds % 60}s`;
} else {
return `${seconds}s`;
}
}
/**
* Safe JSON parse with fallback
*/
export function safeJSONParse<T>(json: string, fallback: T): T {
try {
return JSON.parse(json) || fallback;
} catch {
return fallback;
}
}
/**
* Check if localStorage is available
*/
export function isStorageAvailable(): boolean {
try {
if (typeof localStorage === 'undefined') return false;
const test = '__storage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch {
return false;
}
}