87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
// Utilitaires centralisés pour éviter la duplication
|
|
|
|
/**
|
|
* Combine les classes CSS en filtrant les valeurs falsy
|
|
* Remplace les fonctions mergeClasses et cn dupliquées
|
|
*/
|
|
export const cn = (...classes: (string | undefined | null | false)[]): string => {
|
|
return classes.filter(Boolean).join(' ');
|
|
};
|
|
|
|
/**
|
|
* Hook personnalisé pour gérer le scroll du body
|
|
* Factorisation de la logique répétée dans plusieurs composants
|
|
*/
|
|
export const useBodyScrollLock = (isLocked: boolean) => {
|
|
const originalStyle = document.body.style.overflow;
|
|
|
|
if (isLocked) {
|
|
document.body.style.overflow = 'hidden';
|
|
} else {
|
|
document.body.style.overflow = originalStyle || 'unset';
|
|
}
|
|
|
|
// Cleanup function
|
|
return () => {
|
|
document.body.style.overflow = originalStyle || 'unset';
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Configuration de navigation centralisée
|
|
*/
|
|
export const createNavClickHandler = (onClose?: () => void) => {
|
|
return (sectionId: string) => {
|
|
if (sectionId === 'home') {
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
} else if (sectionId === 'contact') {
|
|
window.location.href = 'mailto:contact@la-banquise.fr';
|
|
} else {
|
|
const element = document.getElementById(sectionId);
|
|
if (element) {
|
|
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
}
|
|
}
|
|
onClose?.();
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Gestionnaire d'événements de redimensionnement optimisé
|
|
*/
|
|
export const useResizeHandler = (callback: () => void, breakpoint: number = 768) => {
|
|
const handleResize = () => {
|
|
if (window.innerWidth >= breakpoint) {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
return () => window.removeEventListener('resize', handleResize);
|
|
};
|
|
|
|
/**
|
|
* Classes CSS communes pour éviter la répétition
|
|
*/
|
|
export const commonClasses = {
|
|
// Transitions
|
|
transition: 'transition-all duration-300 ease-in-out',
|
|
transitionFast: 'transition-all duration-200 ease-in-out',
|
|
|
|
// Hover effects communs
|
|
hoverLift: 'hover:-translate-y-1 hover:shadow-xl hover:scale-105',
|
|
hoverScale: 'hover:scale-105 active:scale-95',
|
|
|
|
// Boutons communs
|
|
buttonBase: 'inline-flex items-center justify-center font-semibold rounded-xl transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-blue-400/50',
|
|
|
|
// Navigation
|
|
navLink: 'px-4 py-2.5 text-white/90 hover:text-white font-medium rounded-xl transition-all duration-300 hover:bg-white/10',
|
|
|
|
// Cards
|
|
cardBase: 'backdrop-blur-lg rounded-2xl border transition-all duration-300',
|
|
cardHover: 'hover:shadow-xl hover:-translate-y-1',
|
|
|
|
// Mobile menu items
|
|
mobileMenuItem: 'group flex items-center justify-between p-4 rounded-xl transition-all duration-300 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20',
|
|
} as const; |