fontmap / src /components /FontMap /hooks /useArrowNavigation.js
tfrere's picture
tfrere HF Staff
first commit
eebc40f
raw
history blame
4.92 kB
import { useEffect, useCallback } from 'react';
/**
* Hook pour la navigation aux flèches entre les polices
* Permet de naviguer vers la police la plus proche dans la direction souhaitée
*/
export const useArrowNavigation = (
selectedFont,
fonts,
filter,
searchTerm,
onFontSelect
) => {
// Fonction pour filtrer les polices selon les critères actuels
const getFilteredFonts = useCallback(() => {
if (!fonts || fonts.length === 0) return [];
return fonts.filter(font => {
// Filtrage par famille
const familyMatch = filter === 'all' || font.family === filter;
// Filtrage par recherche
const searchMatch = !searchTerm ||
font.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
font.family.toLowerCase().includes(searchTerm.toLowerCase());
return familyMatch && searchMatch;
});
}, [fonts, filter, searchTerm]);
// Fonction pour calculer la distance entre deux polices
const calculateDistance = useCallback((font1, font2) => {
if (!font1 || !font2 || !font1.x || !font1.y || !font2.x || !font2.y) {
return Infinity;
}
const dx = font1.x - font2.x;
const dy = font1.y - font2.y;
return Math.sqrt(dx * dx + dy * dy);
}, []);
// Fonction pour trouver la police la plus proche dans une direction
const findNearestFontInDirection = useCallback((direction) => {
if (!selectedFont || !onFontSelect) return;
const filteredFonts = getFilteredFonts();
if (filteredFonts.length <= 1) return; // Pas assez de polices pour naviguer
// Trouver la police sélectionnée dans la liste filtrée
const currentFont = filteredFonts.find(font => font.name === selectedFont.name);
if (!currentFont) return;
let bestFont = null;
let bestDistance = Infinity;
// Approche simple : trouver la police la plus proche dans la direction
filteredFonts.forEach(font => {
if (font.name === selectedFont.name) return; // Ignorer la police actuelle
const dx = font.x - currentFont.x;
const dy = font.y - currentFont.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance === 0) return; // Éviter les polices à la même position
let isInDirection = false;
// Vérifier si la police est dans la direction souhaitée (critères simples)
switch (direction) {
case 'ArrowUp':
// Police au-dessus - inversé car les coordonnées semblent inversées
isInDirection = dy > 0 && Math.abs(dx) <= Math.abs(dy) * 2;
break;
case 'ArrowDown':
// Police en-dessous - inversé car les coordonnées semblent inversées
isInDirection = dy < 0 && Math.abs(dx) <= Math.abs(dy) * 2;
break;
case 'ArrowLeft':
// Police à gauche (x plus petit) - accepter un peu de décalage vertical
isInDirection = dx < 0 && Math.abs(dy) <= Math.abs(dx) * 2;
break;
case 'ArrowRight':
// Police à droite (x plus grand) - accepter un peu de décalage vertical
isInDirection = dx > 0 && Math.abs(dy) <= Math.abs(dx) * 2;
break;
default:
return;
}
// Si la police est dans la bonne direction et plus proche que la meilleure actuelle
if (isInDirection && distance < bestDistance) {
bestDistance = distance;
bestFont = font;
}
});
// Sélectionner la police la plus proche trouvée
if (bestFont) {
onFontSelect(bestFont);
}
}, [selectedFont, getFilteredFonts, onFontSelect]);
// Gestionnaire d'événements clavier
const handleKeyDown = useCallback((event) => {
// Vérifier si une police est sélectionnée
if (!selectedFont) return;
// Vérifier si on est dans un champ de saisie
const activeElement = document.activeElement;
if (activeElement && (
activeElement.tagName === 'INPUT' ||
activeElement.tagName === 'TEXTAREA' ||
activeElement.contentEditable === 'true'
)) {
return; // Ne pas intercepter les flèches dans les champs de saisie
}
// Gérer les touches fléchées
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
event.preventDefault(); // Empêcher le scroll de la page
findNearestFontInDirection(event.key);
}
}, [selectedFont, findNearestFontInDirection]);
// Ajouter l'écouteur d'événements
useEffect(() => {
window.addEventListener('keydown', handleKeyDown);
return () => {
window.removeEventListener('keydown', handleKeyDown);
};
}, [handleKeyDown]);
// Retourner des informations utiles pour le debug
return {
canNavigate: selectedFont && getFilteredFonts().length > 1,
filteredFontsCount: getFilteredFonts().length,
selectedFontName: selectedFont?.name
};
};